package cn.lili.modules.promotion.serviceimpl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.promotion.entity.dos.Ticket;
import cn.lili.modules.promotion.entity.dos.TicketArea;
import cn.lili.modules.promotion.entity.dos.TicketCanvas;
import cn.lili.modules.promotion.entity.dto.search.TicketExportParams;
import cn.lili.modules.promotion.entity.enums.TicketSaleStateEnum;
import cn.lili.modules.promotion.entity.vos.*;
import cn.lili.modules.promotion.mapper.TicketMapper;
import cn.lili.modules.promotion.service.TicketAreaService;
import cn.lili.modules.promotion.service.TicketCanvasService;
import cn.lili.modules.promotion.service.TicketService;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket>
        implements TicketService {

    private final TicketCanvasService ticketCanvasService;

    private final TicketAreaService ticketAreaService;

    private final List<String> ticketImportCells = new ArrayList<>(List.of(
            "编号", "区域", "区域方向", "排", "列", "座位号", "门票", "门票类型"));

    /**
     * 分页查询座位
     *
     * @param searchParams
     * @param page
     * @return
     */
    @Override
    public Page<Ticket> getByPage(Ticket searchParams, PageVO page) {
        LambdaQueryWrapper<Ticket> queryWrapper = buildQuery(searchParams);
        return this.baseMapper.selectPage(PageUtil.initPage(page), queryWrapper);
    }

    @NotNull
    private static LambdaQueryWrapper<Ticket> buildQuery(Ticket searchParams) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        queryWrapper.eq(StringUtils.isNotEmpty(searchParams.getAreaId()), Ticket::getAreaId, searchParams.getAreaId());
        queryWrapper.like(StringUtils.isNotEmpty(searchParams.getSeat()), Ticket::getSeat, searchParams.getSeat());
        queryWrapper.like(StringUtils.isNotEmpty(searchParams.getTicket()), Ticket::getTicket, searchParams.getTicket());
        queryWrapper.eq(null != searchParams.getTicketType(), Ticket::getTicketType, searchParams.getTicketType());
        queryWrapper.eq(StringUtils.isNotEmpty(searchParams.getSaleState()), Ticket::getSaleState, searchParams.getSaleState());
        queryWrapper.like(StringUtils.isNotEmpty(searchParams.getBuyerName()), Ticket::getBuyerName, searchParams.getBuyerName());
        queryWrapper.like(StringUtils.isNotEmpty(searchParams.getOrderNo()), Ticket::getOrderNo, searchParams.getOrderNo());
        queryWrapper.eq(null != searchParams.getDownState(), Ticket::getDownState, searchParams.getDownState());
        queryWrapper.orderByDesc(Ticket::getCreateTime);
        return queryWrapper;
    }


    /**
     * 生成座位号
     *
     * @param params
     */
    @Override
    public void generateTicket(TicketAddVO params) {
        if (StringUtils.isEmpty(params.getAreaId()) || null == params.getRowNumbers()
                || null == params.getColumnNumbers() || StringUtils.isEmpty(params.getAreaDirection())) {
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        }
        if (params.getTicketVOList().isEmpty()) {
            throw new ServiceException("请选择座位");
        }
        TicketArea ticketArea = ticketAreaService.getById(params.getAreaId());
        if (null == ticketArea) {
            throw new ServiceException("所选区域不存在");
        }
        // 更新画布信息
        TicketCanvas ticketCanvas = ticketCanvasService.getByArea(params.getAreaId(), params.getAreaDirection());
        if (null == ticketCanvas) {
            ticketCanvas = new TicketCanvas();
            ticketCanvas.setId(SnowFlake.getIdStr());
            ticketCanvas.setAreaId(params.getAreaId());
            ticketCanvas.setAreaName(ticketArea.getAreaName());
            ticketCanvas.setLineNumber(params.getRowNumbers());
            ticketCanvas.setColumnNumber(params.getColumnNumbers());
            ticketCanvas.setAreaDirection(params.getAreaDirection());
            ticketCanvasService.save(ticketCanvas);
        }else {
            ticketCanvas.setLineNumber(params.getRowNumbers());
            ticketCanvas.setColumnNumber(params.getColumnNumbers());
            ticketCanvasService.updateById(ticketCanvas);
        }

        for (TicketVO ticketVO : params.getTicketVOList()) {
            // 获取已生成的座位号
            Ticket ticket = getByParams(params.getCanvasId(), params.getAreaId(), ticketVO.getLine(), ticketVO.getColumn());
            if (null == ticket) {
                ticket = new Ticket();
                ticket.setId(SnowFlake.getIdStr());
                ticket.setColumnNumbers(ticketVO.getColumn());
                ticket.setRowNumbers(ticketVO.getLine());
                ticket.setAreaId(params.getAreaId());
                ticket.setAreaName(ticketArea.getAreaName());
                ticket.setCanvasId(ticketCanvas.getId());
                ticket.setAreaDirection(ticketCanvas.getAreaDirection());
                ticket.setDownState(0);
                ticket.setSaleState(TicketSaleStateEnum.ONSALE.name());
                ticket.setSeat(ticketArea.getAreaName() + "-" + ticketCanvas.getAreaDirection()
                        + "-" + ticketVO.getLine() + "-" + ticketVO.getColumn());
                this.save(ticket);
            }
        }
    }



    /**
     * 删除在售状态的座位
     * @param canvasId
     * @param lines
     * @param rows
     */
    public void deleteTicket(String canvasId) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getCanvasId, canvasId);
        queryWrapper.eq(Ticket::getSaleState, TicketSaleStateEnum.ONSALE.name());
        this.remove(queryWrapper);
    }

    public Ticket queryTicket(String area, String areaDirection, String lines, String rows, String seat) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        queryWrapper.eq(Ticket::getAreaName, area);
        queryWrapper.eq(Ticket::getAreaDirection, areaDirection);
        queryWrapper.eq(Ticket::getRowNumbers, lines);
        queryWrapper.eq(Ticket::getColumnNumbers, rows);
        queryWrapper.eq(Ticket::getSeat, seat);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    /**
     * 导出座位
     *
     * @param params
     * @return
     */
    @Override
    public List<Ticket> exportTicket(TicketExportParams params) {
        if (null == params.getExportType()) {
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        }

        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        // 导出所有
        if (params.getExportType() == 0) {
            // 为空导出所有座位号，不为空导出指定区域
            if (!StringUtils.isEmpty(params.getArea())) {
                queryWrapper.eq(Ticket::getAreaId, params.getArea());
            }
        } else { // 导出选中数据
            if (params.getIds().isEmpty()) {
                throw new ServiceException("没有选中数据");
            }
            queryWrapper.in(Ticket::getId, params.getIds());
        }
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        return this.list(queryWrapper);
    }


    /**
     * 导入门票
     *
     * @param file
     * @throws IOException
     */
    @Override
    public void importTicket(MultipartFile file) throws Exception {
        InputStream is = file.getInputStream();
        ExcelReader excelReader = ExcelUtil.getReader(is);
        List<List<Object>> read = excelReader.read(1, excelReader.getRowCount());
        for (List<Object> objects : read) {
            int noColNum = getCellIndex("编号");
            if (CharSequenceUtil.isEmpty(objects.get(noColNum).toString())) {
                throw new ServiceException("编号不能为空");
            }
            int areaColNum = getCellIndex("区域");
            if (CharSequenceUtil.isEmpty(objects.get(areaColNum).toString())) {
                throw new ServiceException("区域不能为空");
            }
            int areaDirectionColumn = getCellIndex("区域方向");
            if (CharSequenceUtil.isEmpty(objects.get(areaDirectionColumn).toString())) {
                throw new ServiceException("区域方向不能为空");
            }
            int lineColNum = getCellIndex("排");
            if (CharSequenceUtil.isEmpty(objects.get(lineColNum).toString())) {
                throw new ServiceException("排号不能为空");
            }

            int rowColNum = getCellIndex("列");
            if (CharSequenceUtil.isEmpty(objects.get(rowColNum).toString())) {
                throw new ServiceException("列号不能为空");
            }
            int seatColNum = getCellIndex("座位号");
            if (CharSequenceUtil.isEmpty(objects.get(seatColNum).toString())) {
                throw new ServiceException("座位号不能为空");
            }
            int ticketColNum = getCellIndex("门票");
            if (CharSequenceUtil.isEmpty(objects.get(ticketColNum).toString())) {
                throw new ServiceException("门票号不能为空");
            }

            int ticketTypeColNum = getCellIndex("门票类型");

            String area = objects.get(areaColNum).toString().trim();
            String line = objects.get(lineColNum).toString().trim();
            String row = objects.get(rowColNum).toString().trim();
            String seat = objects.get(seatColNum).toString().trim();
            String ticketNo = objects.get(ticketColNum).toString().trim();
            String areaDirection = objects.get(areaDirectionColumn).toString().trim();
            String id = objects.get(noColNum).toString().trim();
            //String ticketType = String.valueOf(objects.get(ticketTypeColNum));
            //Ticket ticket = queryTicket(area, areaDirection, line, row, seat);
            Ticket ticket = this.getById(id);
            if (null == ticket) {
                throw new ServiceException("导入失败，【" + area + line + "-" + row + "-" + seat + "】");
            }
            if (TicketSaleStateEnum.LOCKSALE.name().equals(ticket.getSaleState())
                    || TicketSaleStateEnum.OFFSALE.name().equals(ticket.getSaleState())) {
                continue;
            }
            if (StringUtils.isNotEmpty(ticketNo)) {
                if (ticketNo.equals(ticket.getTicket())) {
                    continue;
                }
            }
            ticket.setTicket(ticketNo);
            if (ticketTypeColNum >= 7) {
                ticket.setTicketType(1);
            }else {
                String ticketType = String.valueOf(objects.get(ticketTypeColNum)).trim();
                if (StringUtils.isEmpty(ticketType) || "座票".equals(ticketType)) {
                    ticket.setTicketType(1);
                }else {
                    ticket.setTicketType(0);
                }
            }


            if (null == ticket.getDownState()) {
                ticket.setDownState(0);
            }
            this.updateById(ticket);
        }
    }

    /**
     * 编辑门票号
     *
     * @param id
     */
    @Override
    public void updateTicketById(Ticket ticket) {
        Ticket ticket1 = this.getById(ticket.getId());
        if (null == ticket) {
            throw new ServiceException("座位信息不存在");
        }
        if (ticket.getTicket().equals(ticket1.getTicket())) {
            throw new ServiceException("门票不能重复");
        }
        updateById(ticket);
    }

    /**
     * 更新上下架状态
     *
     * @param id
     */
    @Override
    public void updateDownState(String id, Integer state) {
        Ticket ticket = this.getById(id);
        if (null == ticket) {
            throw new ServiceException("座位信息不存在");
        }
        if (state == 1 && StringUtils.isEmpty(ticket.getTicket())) {
            throw new ServiceException("请先配置门票号");
        }
        ticket.setDownState(state);
        updateById(ticket);
    }

    public Ticket getByParams (String canvasId, String areaId, Integer line, Integer row) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        queryWrapper.eq(Ticket::getAreaId, areaId);
        queryWrapper.eq(Ticket::getCanvasId, canvasId);
        queryWrapper.eq(Ticket::getRowNumbers, line);
        queryWrapper.eq(Ticket::getColumnNumbers, row);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    /**
     * 根据画布查询座位
     * @param canvasId
     * @return
     */
    @Override
    public List<Ticket> getByCanvasId (String canvasId) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        queryWrapper.eq(Ticket::getCanvasId, canvasId);
        return this.list(queryWrapper);
    }

    /**
     * 删除门票
     * @param id
     */
    @Override
    public void deleteById (String id) {
        Ticket ticket = this.getById(id);
        if (null == ticket) {
            throw new ServiceException("座位不存在");
        }
        if (ticket.getDownState() == 1) {
            throw new ServiceException("门票已上架，不能删除");
        }
        if (TicketSaleStateEnum.OFFSALE.name().equals(ticket.getSaleState())) {
            throw new ServiceException("该门票已出售，不能删除");
        }
        ticket.setDeleteFlag(true);
        this.updateById(ticket);
    }


    private int getCellIndex(String cellName) {
        return ticketImportCells.indexOf(cellName);
    }

    /**
     * 获取座位号信息
     *
     * @param areaName 区域名称
     * @param areaDirection    区域方向
     * @param line 行
     * @param column 列
     */
    @Override
    public Ticket getTicket(String areaName, String areaDirection, String line, String column) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        queryWrapper.eq(StringUtils.isNotEmpty(areaName), Ticket::getAreaName, areaName);
        queryWrapper.eq(StringUtils.isNotEmpty(areaDirection), Ticket::getAreaDirection, areaDirection);
        queryWrapper.eq(StringUtils.isNotEmpty(line), Ticket::getRowNumbers, line);
        queryWrapper.eq(StringUtils.isNotEmpty(column), Ticket::getColumnNumbers, column);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    /**
     * 根据前端画布大小查询座位
     * @param areaName
     * @param areaDirection
     * @param startNumber
     * @param rowEnd
     * @param columnEnd
     * @return
     */
    @Override
    public List<Ticket> getTicketBySize (String areaName, String areaDirection,
                                         Integer rowStart, Integer columnStart,
                                         Integer rowEnd, Integer columnEnd) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getDeleteFlag, 0);
        queryWrapper.eq(Ticket::getAreaName, areaName);
        queryWrapper.eq(Ticket::getAreaDirection, areaDirection);
        queryWrapper.ge(Ticket::getRowNumbers, rowStart);
        queryWrapper.le(Ticket::getRowNumbers, rowEnd);
        queryWrapper.ge(Ticket::getColumnNumbers, columnStart);
        queryWrapper.le(Ticket::getColumnNumbers, columnEnd);
        return this.list(queryWrapper);
    }

    /**
     * 删除门票
     * @param id
     */
    public void delete (String id) {
        Ticket ticket = this.getById(id);
        if (null == ticket) {
            throw new ServiceException("门票不存在");
        }
        ticket.setDeleteFlag(true);
        this.updateById(ticket);
    }

    /**
     * 批量售出座位
     * @param ticketAddVOList
     */
    @Override
    public void batchSale (TicketBatchSaleVO batchSaleVO) {
        if (StringUtils.isEmpty(batchSaleVO.getScene()) || StringUtils.isEmpty(batchSaleVO.getUserId())) {
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        }
        if (batchSaleVO.getIdList().isEmpty()) {
            throw new ServiceException("请选择座位");
        }
        for (String id : batchSaleVO.getIdList()) {
            Ticket ticket = this.getById(id);
            if (null != ticket) {
                if (TicketSaleStateEnum.OFFSALE.name().equals(ticket.getSaleState())
                        || TicketSaleStateEnum.LOCKSALE.name().equals(ticket.getSaleState())
                        || ticket.getDownState() == 0
                        || StringUtils.isEmpty(ticket.getTicket())) {
                    continue;
                }

                ticket.setBuyerId(batchSaleVO.getUserId());
                ticket.setBuyerName(batchSaleVO.getUserName());
                ticket.setScene(batchSaleVO.getScene());
                ticket.setSaleState(TicketSaleStateEnum.OFFSALE.name());
                this.updateById(ticket);
            }
        };
    }


    /**
     * 批量上下架
     * @param batchDownStateVO
     */
    @Override
    public void batchDownState(TicketBatchDownStateVO batchDownStateVO) {
        if (batchDownStateVO.getIdList().isEmpty() || null == batchDownStateVO.getDownState()) {
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        }
        for (String id : batchDownStateVO.getIdList()) {
            Ticket ticket = this.getById(id);
            if (null != ticket && TicketSaleStateEnum.OFFSALE.name().equals(ticket.getSaleState())) {
                continue;
            }
            ticket.setDownState(batchDownStateVO.getDownState());
            this.updateById(ticket);
        }
    }
}